using DeviceCommons.DataHandling;
using DeviceCommons.DeviceMessages.Enums;
using DeviceCommons.DeviceMessages.Models.V1;
using System.Text;

namespace DeviceCommons.DeviceMessages.Factories
{
    /// <summary>
    /// 快速读数状态工厂实现
    /// 根据设备类型配置计算偏移量MAP并直接解析状态
    /// </summary>
    public class FastReadingStateFactory : IFastReadingStateFactory
    {
        /// <summary>
        /// 检查设备类型是否支持快速解析
        /// </summary>
        /// <param name="deviceType">设备类型</param>
        /// <returns>是否支持快速解析</returns>
        public bool SupportsFastParsing(byte deviceType)
        {
            return DeviceStateConfigurationRegistry.IsRegistered(deviceType);
        }

        /// <summary>
        /// 快速解析读数状态
        /// </summary>
        /// <param name="bytes">状态数据字节数组</param>
        /// <param name="deviceType">设备类型</param>
        /// <returns>解析后的读数状态</returns>
        public IDeviceMessageInfoReadingStates ParseReadingStates(ReadOnlySpan<byte> bytes, byte deviceType)
        {
            var configuration = DeviceStateConfigurationRegistry.GetConfiguration(deviceType);
            if (configuration == null)
                throw new InvalidOperationException($"设备类型 {deviceType} 没有注册状态配置");

            var states = new List<IDeviceMessageInfoReadingState>();
            var currentOffset = 1; // 第一个字节是状态数量，从索引1开始

            foreach (var stateDef in configuration.StateDefinitions)
            {
                var (value, nextOffset) = ParseStateValue(bytes, currentOffset, stateDef);
                
                if (value != null)
                {
                    var state = new DeviceMessageInfoReadingState
                    {
                        SID = stateDef.Sid,
                        ValueType = stateDef.ValueType,               // 先设置类型
                        ValueText = value.ToString() ?? string.Empty  // 后设置文本值
                    };
                    // DataLength 是只读属性，通过 Value 数组的长度自动计算
                    states.Add(state);
                }

                currentOffset = nextOffset;
            }

            return new DeviceMessageInfoReadingStates
            {
                StateArray = states.ToArray()
            };
        }

        /// <summary>
        /// 计算设备类型的状态数据总长度
        /// </summary>
        /// <param name="deviceType">设备类型</param>
        /// <returns>状态数据总长度</returns>
        public int CalculateStateDataLength(byte deviceType)
        {
            var configuration = DeviceStateConfigurationRegistry.GetConfiguration(deviceType);
            if (configuration == null) return 0;

            int totalLength = 0;
            foreach (var stateDef in configuration.StateDefinitions)
            {
                // 每个状态都有固定的头部：SID(1字节) + 类型(1字节)
                totalLength += 2;
                
                // 根据类型计算值的大小
                if (stateDef.ValueType == StateValueTypeEnum.String)
                {
                    // 字符串类型：长度(1字节) + 字符串内容
                    // 这里我们无法知道实际字符串长度，所以只能计算最小长度
                    totalLength += 1; // 长度字段
                    // 注意：实际字符串内容长度在运行时才能确定
                }
                else if (stateDef.ValueType == StateValueTypeEnum.Binary)
                {
                    // 二进制类型：长度(2字节) + 二进制内容
                    totalLength += 2; // 长度字段
                    // 注意：实际二进制内容长度在运行时才能确定
                }
                else
                {
                    // 固定长度类型：无长度字段，直接使用类型大小
                    totalLength += GetTypeSize(stateDef.ValueType);
                }
            }
            return totalLength;
        }

        /// <summary>
        /// 解析单个状态值
        /// </summary>
        /// <param name="bytes">字节数组</param>
        /// <param name="offset">起始偏移量</param>
        /// <param name="stateDefinition">状态定义</param>
        /// <returns>解析结果，包含值和下一个状态的偏移量</returns>
        private (object? Value, int NextOffset) ParseStateValue(ReadOnlySpan<byte> bytes, int offset, StateDefinition stateDefinition)
        {
            if (offset < 0 || offset >= bytes.Length)
                return (null, offset);

            try
            {
                // 跳过SID(1字节)和类型(1字节)，直接读取值
                var valueOffset = offset + 2;
                var value = ExtractValueByType(bytes, valueOffset, stateDefinition.ValueType);
                var nextOffset = CalculateNextOffset(offset, stateDefinition.ValueType, value);
                
                return (value, nextOffset);
            }
            catch
            {
                // 解析失败，返回下一个可能的偏移量
                var nextOffset = CalculateNextOffset(offset, stateDefinition.ValueType, null);
                return (null, nextOffset);
            }
        }

        /// <summary>
        /// 根据类型从字节数组中提取值
        /// </summary>
        /// <param name="bytes">字节数组</param>
        /// <param name="offset">偏移量</param>
        /// <param name="valueType">值类型</param>
        /// <returns>提取的值</returns>
        private object? ExtractValueByType(ReadOnlySpan<byte> bytes, int offset, StateValueTypeEnum valueType)
        {
            if (offset < 0 || offset >= bytes.Length)
                return null;

            return valueType switch
            {
                StateValueTypeEnum.String => ExtractString(bytes, offset),
                StateValueTypeEnum.Int32 => ExtractInt32(bytes, offset),
                StateValueTypeEnum.Int16 => ExtractInt16(bytes, offset),
                StateValueTypeEnum.UInt16 => ExtractUInt16(bytes, offset),
                StateValueTypeEnum.Float32 => ExtractFloat32(bytes, offset),
                StateValueTypeEnum.Double => ExtractDouble(bytes, offset),
                StateValueTypeEnum.Bool => ExtractBool(bytes, offset),
                StateValueTypeEnum.Binary => ExtractBinary(bytes, offset),
                StateValueTypeEnum.Timestamp => ExtractTimestamp(bytes, offset),
                _ => null
            };
        }

        /// <summary>
        /// 计算下一个状态的偏移量
        /// </summary>
        /// <param name="currentOffset">当前偏移量</param>
        /// <param name="valueType">值类型</param>
        /// <param name="value">解析出的值（用于变长类型）</param>
        /// <returns>下一个状态的偏移量</returns>
        private int CalculateNextOffset(int currentOffset, StateValueTypeEnum valueType, object? value)
        {
            // 每个状态都有固定的头部：SID(1字节) + 类型(1字节)
            var headerSize = 2;
            
            // 根据类型计算值的大小
            if (valueType == StateValueTypeEnum.String && value is string str)
            {
                // 字符串类型：长度(1字节) + 字符串内容
                var stringLength = Encoding.UTF8.GetByteCount(str);
                return currentOffset + headerSize + 1 + stringLength;
            }
            else if (valueType == StateValueTypeEnum.Binary && value is byte[] binary)
            {
                // 二进制类型：长度(2字节) + 二进制内容
                return currentOffset + headerSize + 2 + binary.Length;
            }
            else
            {
                // 固定长度类型：无长度字段，直接使用类型大小
                var typeSize = GetTypeSize(valueType);
                return currentOffset + headerSize + typeSize;
            }
        }

        /// <summary>
        /// 获取类型的字节大小
        /// </summary>
        /// <param name="valueType">值类型</param>
        /// <returns>字节大小</returns>
        private int GetTypeSize(StateValueTypeEnum valueType)
        {
            // 对于固定长度类型，使用 DeviceMessageUtilities.GetValueLength 获取固定长度
            // 传递 null 作为数据参数，因为我们只需要固定长度
            return DeviceMessageUtilities.GetValueLength(valueType, null);
        }

        // 各种类型的值提取方法
        private string ExtractString(ReadOnlySpan<byte> bytes, int offset)
        {
            if (offset + 1 > bytes.Length) return string.Empty;
            
            var length = bytes[offset]; // 字符串长度（1字节）
            if (length <= 0 || offset + 1 + length > bytes.Length) return string.Empty;
            
            var result = Encoding.UTF8.GetString(bytes.Slice(offset + 1, length)).Trim('\0');
            return result;
        }

        private int ExtractInt32(ReadOnlySpan<byte> bytes, int offset)
        {
            if (offset + 4 > bytes.Length) return 0;
            return BitConverter.ToInt32(bytes.Slice(offset, 4));
        }

        private short ExtractInt16(ReadOnlySpan<byte> bytes, int offset)
        {
            if (offset + 2 > bytes.Length) return 0;
            return BitConverter.ToInt16(bytes.Slice(offset, 2));
        }

        private ushort ExtractUInt16(ReadOnlySpan<byte> bytes, int offset)
        {
            if (offset + 2 > bytes.Length) return 0;
            return BitConverter.ToUInt16(bytes.Slice(offset, 2));
        }

        private float ExtractFloat32(ReadOnlySpan<byte> bytes, int offset)
        {
            if (offset + 4 > bytes.Length) return 0.0f;
            return BitConverter.ToSingle(bytes.Slice(offset, 4));
        }

        private double ExtractDouble(ReadOnlySpan<byte> bytes, int offset)
        {
            if (offset + 8 > bytes.Length) return 0.0;
            return BitConverter.ToDouble(bytes.Slice(offset, 8));
        }

        private bool ExtractBool(ReadOnlySpan<byte> bytes, int offset)
        {
            if (offset >= bytes.Length) return false;
            return bytes[offset] != 0;
        }

        private byte[] ExtractBinary(ReadOnlySpan<byte> bytes, int offset)
        {
            if (offset + 2 > bytes.Length) return new byte[0];
            
            var length = BitConverter.ToUInt16(bytes.Slice(offset, 2));
            if (length <= 0 || offset + 2 + length > bytes.Length) return new byte[0];
            
            var result = new byte[length];
            bytes.Slice(offset + 2, length).CopyTo(result);
            return result;
        }

        private ulong ExtractTimestamp(ReadOnlySpan<byte> bytes, int offset)
        {
            if (offset + 8 > bytes.Length) return 0;
            return BitConverter.ToUInt64(bytes.Slice(offset, 8));
        }
    }
}
